const Joi = require('joi');

/**
 * 通用验证工具
 */

// 常用的验证模式
const commonSchemas = {
  // MongoDB ObjectId
  objectId: Joi.string().pattern(/^[0-9a-fA-F]{24}$/).message('Invalid ObjectId format'),
  
  // 租户ID (nanoid格式)
  tenantId: Joi.string().alphanum().min(10).max(30).required(),
  
  // 邮箱
  email: Joi.string().email().lowercase().trim().required(),
  
  // 密码 (至少8位，包含大小写字母和数字)
  password: Joi.string()
    .min(8)
    .max(128)
    .pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
    .message('Password must contain at least 8 characters with uppercase, lowercase and number')
    .required(),
  
  // 用户名
  username: Joi.string().alphanum().min(3).max(30).trim(),
  
  // 域名
  domain: Joi.string()
    .pattern(/^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/)
    .message('Invalid domain format'),
  
  // 子域名
  subdomain: Joi.string()
    .pattern(/^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/)
    .message('Invalid subdomain format'),
  
  // URL
  url: Joi.string().uri(),
  
  // 电话号码
  phone: Joi.string().pattern(/^\+?[1-9]\d{1,14}$/).message('Invalid phone number format'),
  
  // 分页参数
  pagination: {
    page: Joi.number().integer().min(1).default(1),
    limit: Joi.number().integer().min(1).max(100).default(10),
    sort: Joi.string().valid('asc', 'desc').default('desc'),
    sortBy: Joi.string().default('createdAt')
  },
  
  // 日期范围
  dateRange: {
    startDate: Joi.date().iso(),
    endDate: Joi.date().iso().min(Joi.ref('startDate'))
  }
};

/**
 * 验证请求数据
 * @param {Object} schema - Joi验证模式
 * @param {Object} data - 要验证的数据
 * @param {Object} options - 验证选项
 * @returns {Object} 验证结果
 */
function validateData(schema, data, options = {}) {
  const defaultOptions = {
    abortEarly: false,
    allowUnknown: false,
    stripUnknown: true,
    ...options
  };
  
  const { error, value } = schema.validate(data, defaultOptions);
  
  if (error) {
    const validationError = new Error('Validation failed');
    validationError.statusCode = 400;
    validationError.validation = error.details.map(detail => ({
      field: detail.path.join('.'),
      message: detail.message,
      value: detail.context?.value
    }));
    validationError.validationContext = error.details[0]?.context;
    throw validationError;
  }
  
  return value;
}

/**
 * 创建验证中间件
 * @param {Object} schema - Joi验证模式
 * @param {string} source - 数据源 ('body', 'query', 'params')
 * @returns {Function} Fastify中间件函数
 */
function createValidationMiddleware(schema, source = 'body') {
  return async function validationMiddleware(request, reply) {
    try {
      const data = request[source];
      request[source] = validateData(schema, data);
    } catch (error) {
      throw error;
    }
  };
}

/**
 * 验证租户上下文
 * @param {Object} data - 包含租户信息的数据
 * @returns {boolean} 是否有效
 */
function validateTenantContext(data) {
  if (!data || typeof data !== 'object') {
    return false;
  }
  
  // 检查是否有租户标识
  return !!(data.tenantId || data.tenant || data.domain || data.subdomain);
}

/**
 * 清理和标准化数据
 * @param {Object} data - 要清理的数据
 * @returns {Object} 清理后的数据
 */
function sanitizeData(data) {
  if (!data || typeof data !== 'object') {
    return data;
  }
  
  const sanitized = {};
  
  for (const [key, value] of Object.entries(data)) {
    // 跳过空值
    if (value === null || value === undefined || value === '') {
      continue;
    }
    
    // 递归处理对象
    if (typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {
      const nestedSanitized = sanitizeData(value);
      if (Object.keys(nestedSanitized).length > 0) {
        sanitized[key] = nestedSanitized;
      }
    } else if (Array.isArray(value)) {
      // 处理数组
      const sanitizedArray = value.map(item => sanitizeData(item)).filter(item => item !== null && item !== undefined);
      if (sanitizedArray.length > 0) {
        sanitized[key] = sanitizedArray;
      }
    } else {
      // 处理字符串
      if (typeof value === 'string') {
        const trimmed = value.trim();
        if (trimmed.length > 0) {
          sanitized[key] = trimmed;
        }
      } else {
        sanitized[key] = value;
      }
    }
  }
  
  return sanitized;
}

/**
 * 验证文件上传
 * @param {Object} file - 上传的文件
 * @param {Object} options - 验证选项
 * @returns {boolean} 是否有效
 */
function validateFileUpload(file, options = {}) {
  const {
    maxSize = 5 * 1024 * 1024, // 5MB
    allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'],
    allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.pdf']
  } = options;
  
  if (!file) {
    throw new Error('No file provided');
  }
  
  // 检查文件大小
  if (file.size > maxSize) {
    throw new Error(`File size exceeds maximum allowed size of ${maxSize} bytes`);
  }
  
  // 检查文件类型
  if (!allowedTypes.includes(file.mimetype)) {
    throw new Error(`File type ${file.mimetype} is not allowed`);
  }
  
  // 检查文件扩展名
  const extension = file.filename.toLowerCase().substring(file.filename.lastIndexOf('.'));
  if (!allowedExtensions.includes(extension)) {
    throw new Error(`File extension ${extension} is not allowed`);
  }
  
  return true;
}

/**
 * 生成验证错误响应
 * @param {Array} validationErrors - 验证错误数组
 * @returns {Object} 错误响应对象
 */
function createValidationErrorResponse(validationErrors) {
  return {
    success: false,
    message: 'Validation failed',
    errors: validationErrors.map(error => ({
      field: error.field,
      message: error.message,
      value: error.value
    }))
  };
}

module.exports = {
  commonSchemas,
  validateData,
  createValidationMiddleware,
  validateTenantContext,
  sanitizeData,
  validateFileUpload,
  createValidationErrorResponse
};